package study.dubbo.springboot.provider.auth;



import com.google.common.base.Joiner;
import com.google.common.base.Stopwatch;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.slf4j.MDC;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

@Slf4j
@Activate(group = CommonConstants.PROVIDER_SIDE, order = 1)
public class WatchDogFilter implements Filter {

    private static final String X_TRACE_KEY = "trace_key";

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        //cost time
        Stopwatch stopwatch = Stopwatch.createStarted();
        //trace
        String traceKey = RpcContext.getContext().getAttachment(X_TRACE_KEY);
        MDC.put(X_TRACE_KEY, traceKey);

        log.info(">>>>>> i am Provider filter!");

        //method
        String method = build(invocation);
        URL url = invoker.getUrl();
        log.info("{}", url);
        //args
        Object[] args = invocation.getArguments();
        Arrays.asList(args).stream().forEach(e -> {
            log.info("args >>>>>> {}", e.getClass().getName());
        });

        Result result;
        try {
            //invoke
            result = invoker.invoke(invocation);
            //exception
            if (result.hasException()) {
                log.warn("invoke method[{}] exception!", method);
                Throwable throwable = result.getException();
//                throw (RuntimeException) result.getException();
            }
            //
        } catch (RpcException ex) {
            throw ex;
        } finally {
            log.info("[{}] cost time [{}] ms", method, stopwatch.elapsed(TimeUnit.MILLISECONDS));
            MDC.remove(X_TRACE_KEY);
        }
        return result;
    }

    private String build(Invocation invocation) {
        String clazzName = invocation.getInvoker()
                .getInterface()
                .getCanonicalName();
        String methodName = invocation.getMethodName();
        String method = Joiner.on(".")
                .join(clazzName, methodName);
        return method;
    }
}
